package com.xuexiang.xui_lib.component.edittext.materialedittext;

import com.xuexiang.xui_lib.ResourceTable;
import com.xuexiang.xui_lib.component.edittext.materialedittext.validation.*;
import com.xuexiang.xui_lib.util.AttrValue;
import com.xuexiang.xui_lib.util.ColorUtils;
import com.xuexiang.xui_lib.util.LogUtils;

import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorProperty;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.colors.HsvColor;
import ohos.agp.colors.RgbColor;
import ohos.agp.components.*;
import ohos.agp.components.element.AnimatedStateElement;
import ohos.agp.components.element.Element;
import ohos.agp.components.element.PixelMapElement;
import ohos.agp.components.element.VectorElement;
import ohos.agp.render.*;
import ohos.agp.render.opengl.Utils;
import ohos.agp.text.Layout;
import ohos.agp.text.SimpleTextLayout;
import ohos.agp.utils.Color;
import ohos.agp.utils.Point;
import ohos.agp.utils.TextAlignment;
import ohos.app.Context;
import ohos.global.resource.NotExistException;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;
import ohos.media.image.common.Rect;
import ohos.media.image.common.Size;
import ohos.multimodalinput.event.TouchEvent;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class MaterialTextField extends TextField implements ComponentContainer.ArrangeListener, Component.TouchEventListener {
    private static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0x00201, "MaterialEditTextInfo");


    private List<METValidator> validators = new ArrayList<>();
    private boolean autoValidate;


    public static final int FLOATING_LABEL_NONE = 0;
    public static final int FLOATING_LABEL_NORMAL = 1;
    public static final int FLOATING_LABEL_HIGHLIGHT = 2;

    /**
     * the spacing between the main text and the inner top padding.
     */
    private int extraPaddingTop;

    /**
     * the spacing between the main text and the inner bottom padding.
     */
    private int extraPaddingBottom;

    /**
     * the extra spacing between the main text and the left, actually for the left icon.
     */
    private int extraPaddingLeft;

    /**
     * the extra spacing between the main text and the right, actually for the right icon.
     */
    private int extraPaddingRight;

    /**
     * the floating label's text size.
     */
    private int floatingLabelTextSize;

    /**
     * the floating label's text color.
     */
    private int floatingLabelTextColor;

    /**
     * the bottom texts' size.
     */
    private int bottomTextSize;

    /**
     * the spacing between the main text and the floating label.
     */
    private int floatingLabelPadding;

    /**
     * the spacing between the main text and the bottom components (bottom ellipsis, helper/error text, characters counter).
     */
    private int bottomSpacing;

    /**
     * whether the floating label should be shown. default is false.
     */
    private boolean floatingLabelEnabled;

    /**
     * whether to highlight the floating label's text color when focused (with the main color). default is true.
     */
    private boolean highlightFloatingLabel;

    /**
     * the base color of the line and the texts. default is black.
     */
    private int baseColor;

    /**
     * inner top padding
     */
    private int innerPaddingTop;

    /**
     * inner bottom padding
     */
    private int innerPaddingBottom;

    /**
     * inner left padding
     */
    private int innerPaddingLeft;

    /**
     * inner right padding
     */
    private int innerPaddingRight;

    /**
     * the underline's highlight color, and the highlight color of the floating label if app:highlightFloatingLabel is set true in the xml. default is black(when app:darkTheme is false) or white(when app:darkTheme is true)
     */
    private int primaryColor;

    /**
     * the color for when something is wrong.(e.g. exceeding max characters)
     */
    private int errorColor;

    /**
     * min characters count limit. 0 means no limit. default is 0. NOTE: the character counter will increase the View's height.
     */
    private int minCharacters;

    /**
     * max characters count limit. 0 means no limit. default is 0. NOTE: the character counter will increase the View's height.
     */
    private int maxCharacters;

    /**
     * whether to show the bottom ellipsis in singleLine mode. default is false. NOTE: the bottom ellipsis will increase the View's height.
     */
    private boolean singleLineEllipsis;

    /**
     * Always show the floating label, instead of animating it in/out. False by default.
     */
    private boolean floatingLabelAlwaysShown;

    /**
     * Always show the helper text, no matter if the edit text is focused. False by default.
     */
    private boolean helperTextAlwaysShown;

    /**
     * bottom ellipsis's height
     */
    private int bottomEllipsisSize;

    /**
     * min bottom lines count.
     */
    private int minBottomLines;

    /**
     * reserved bottom text lines count, no matter if there is some helper/error text.
     */
    private int minBottomTextLines;

    /**
     * real-time bottom lines count. used for bottom extending/collapsing animation.
     */
    private float currentBottomLines;

    /**
     * bottom lines count.
     */
    private float bottomLines;

    /**
     * Helper text at the bottom
     */
    private String helperText;

    /**
     * Helper text color
     */
    private int helperTextColor = -1;

    /**
     * error text for manually invoked
     */
    private String tempErrorText;

    /**
     * animation fraction of the floating label (0 as totally hidden).
     */
    private float floatingLabelFraction;

    /**
     * whether the floating label is being shown.
     */
    private boolean floatingLabelShown;

    /**
     * the floating label's focusFraction
     */
    private float focusFraction;

    /**
     * The font used for the accent texts (floating label, error/helper text, character counter, etc.)
     */
//    private Typeface accentTypeface;

    /**
     * Text for the floatLabel if different from the hint
     */
    private CharSequence floatingLabelText;

    /**
     * Whether or not to show the underline. Shown by default
     */
    private boolean hideUnderline;

    /**
     * Underline's color
     */
    private int underlineColor;
    /**
     * Underline's height
     */
    private int underlineHeight;
    private int underlineHeightFocused;
    /**
     * Whether to validate as soon as the text has changed. False by default
     */
//    private boolean autoValidate1;

    /**
     * Whether the characters count is valid
     */
    private boolean charactersCountValid;

    /**
     * Whether use animation to show/hide the floating label.
     */
    private boolean floatingLabelAnimating;

    /**
     * Whether check the characters count at the beginning it's shown.
     */
    private boolean checkCharactersCountAtBeginning;

    /**
     * Left Icon
     */
    private PixelMap[] iconLeftBitmaps;

    /**
     * Right Icon
     */
    private PixelMap[] iconRightBitmaps;

    /**
     * Clear Button
     */
    private PixelMap[] clearButtonBitmaps;
    /**
     * showPwIcon Button
     */
    private PixelMap[] showPwIconBitmaps;
    /**
     * hidePwIcon Button
     */
    private PixelMap[] hidePwIconBitmaps;

    private boolean passwordVisible;

    /**
     * Auto validate when focus lost.
     */
    private boolean validateOnFocusLost;

    private boolean showClearButton;
    private boolean showPasswordButton;
    private boolean firstShown;
    private int iconSize;
    private int iconOuterWidth;
    private int iconOuterHeight;
    private int iconPadding;
    private boolean actionButtonTouched;
    private boolean actionButtonClicking;
    private Color textColorStateList;
    private Color textColorHintStateList;
    //    private ArgbEvaluator focusEvaluator = new ArgbEvaluator();
    Paint paint = new Paint();
    Paint textPaint = new Paint();
    SimpleTextLayout textLayout;
    AnimatorValue labelAnimator;
    AnimatorValue labelFocusAnimator;
    AnimatorValue bottomLinesAnimator;
    FocusChangedListener innerFocusChangeListener;


    FocusChangedListener outerFocusChangeListener;
    //private List<METValidator> validators1 = new ArrayList<>();
    private METLengthChecker lengthChecker;

    //    private PasswordTransformationMethod mTransformationMethod;
    public MaterialTextField(Context context) {
        this(context, null);
    }

    public MaterialTextField(Context context, AttrSet attrSet) {
        this(context, attrSet, null);
    }

    public MaterialTextField(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        init(context, attrSet, styleName);
    }

    private void init(Context context, AttrSet attrSet, String styleName) {
        System.out.println("zhangliang==>init1");
        iconSize = AttrHelper.vp2px(32, context);
        iconOuterWidth = AttrHelper.vp2px(24, context);
        iconOuterHeight = AttrHelper.vp2px(32, context);
        //MaterialEditText
        bottomSpacing = AttrHelper.vp2px(8, context);
        bottomEllipsisSize = AttrHelper.vp2px(4, context);
        System.out.println("zhangliang==>init2");
//        Color defaultBaseColor = Color.BLACK;
//        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MaterialEditText, defStyleAttr, 0);
        textColorStateList = AttrValue.get(attrSet, "met_textColor", Color.BLACK);
//        textColorStateList = attrSet.getAttr("met_textColor").get().getColorValue();//输入文字的颜色
        textColorHintStateList = AttrValue.get(attrSet, "met_textColorHint", Color.GRAY);
//        textColorHintStateList =attrSet.getAttr("met_textColorHint").get().getColorValue();//提示文字的颜色
//
//
        System.out.println("zhangliang==>init3");
        baseColor = AttrValue.get(attrSet, "met_baseColor", Color.getIntColor("#000000"));// 线和文字的基础颜色，默认是black
        primaryColor = AttrValue.get(attrSet, "met_primaryColor", baseColor);//高亮样式的颜色
        setFloatingLabelInternal(AttrValue.get(attrSet, "met_floatingLabel", 0));//0,1,2
//        setFloatingLabelInternal(attrSet.getAttr("met_floatingLabel").get().getIntegerValue());//0,1,2
        errorColor = AttrValue.get(attrSet, "met_errorColor", context.getColor(ResourceTable.Color_xui_config_color_red));
//        errorColor = attrSet.getAttr("met_errorColor").get().getIntegerValue();//出现错误的颜色
        boolean allowEmpty = AttrValue.get(attrSet, "met_allowEmpty", true);
//        boolean allowEmpty = attrSet.getAttr("met_allowEmpty").get().getBoolValue();;//是否允许为空
        System.out.println("zhangliang==>init4");
        if (!allowEmpty) {
            String errorEmpty = attrSet.getAttr("met_errorEmpty").get().getStringValue();
            if (!TextUtils.isEmpty(errorEmpty)) {
                validators.add(new NotAllowEmptyValidator(errorEmpty));
            } else {
                validators.add(new NotAllowEmptyValidator("输入不能为空"));
            }
        }

        minCharacters = AttrValue.get(attrSet, "met_minCharacters", 0);
//        minCharacters = attrSet.getAttr("met_minCharacters").get().getIntegerValue(); //最少文字的限制（0代表无限）
        maxCharacters = AttrValue.get(attrSet, "met_minCharacters", 0);//最多文字的限制（0代表无限）
//        maxCharacters = attrSet.getAttr("met_maxCharacters").get().getIntegerValue(); //最多文字的限制（0代表无限）
        singleLineEllipsis = AttrValue.get(attrSet, "met_singleLineEllipsis", false);
//        singleLineEllipsis = attrSet.getAttr("met_singleLineEllipsis").get().getBoolValue();// 底部文字是否显示单行，显示不全的省略号
//        helperText = attrSet.getAttr("met_helperText").get().getStringValue();// 在底部的辅助文字
        helperText = AttrValue.get(attrSet, "met_helperTextColor", "");
        helperTextColor = AttrValue.get(attrSet, "met_helperTextColor", -1);
//        helperTextColor = attrSet.getAttr("met_helperTextColor").get().getIntegerValue();//在底部的辅助文字颜色
        minBottomTextLines = AttrValue.get(attrSet, "met_helperTextColor", 0);
//        minBottomTextLines = attrSet.getAttr("met_helperTextColor").get().getIntegerValue();// 底部文字最小的行数
        System.out.println("zhangliang==>init5");

//        String fontPathForAccent = attrSet.getAttr("met_accentTypeface").get().getStringValue();// 强调文字的字体
//        if (fontPathForAccent != null) {
//            //设置文字字体
////            accentTypeface = XUI.getDefaultTypeface(fontPathForAccent);//
////            textPaint.setTypeface(accentTypeface);
//        }
//        String fontPathForView = attrSet.getAttr("met_typeface").get().getStringValue();//输入框字体
//        if (fontPathForView != null) {
////            Typeface typeface = XUI.getDefaultTypeface(fontPathForView);
////            setTypeface(typeface);
//        }
        floatingLabelText = AttrValue.get(attrSet, "met_floatingLabelText", "空");//自定义悬浮提示文字
//        floatingLabelText = attrSet.getAttr("met_floatingLabelText").get().getStringValue();//自定义悬浮提示文字
        if (floatingLabelText == null) {
            floatingLabelText = getHint();
        }

//      floatingLabelPadding = typedArray.getDimensionPixelSize(R.styleable.MaterialEditText_met_floatingLabelPadding, bottomSpacing);//输入框文字与悬浮提示文字的间距
        floatingLabelPadding = AttrValue.get(attrSet, "met_floatingLabelPadding", bottomSpacing);//输入框文字与悬浮提示文字的间距
        floatingLabelTextSize = AttrValue.get(attrSet, "met_floatingLabelTextSize", 12);//悬浮提示文字的大小（默认12sp）
        floatingLabelTextColor = AttrValue.get(attrSet, "met_floatingLabelTextColor", -1);
        ;//悬浮提示文字的颜色
        floatingLabelAnimating = AttrValue.get(attrSet, "met_floatingLabelAnimating", true);//是否使用动画显示悬浮提示（默认true）
        bottomTextSize = AttrValue.get(attrSet, "met_bottomTextSize", 12);//底部文字大小
        hideUnderline = AttrValue.get(attrSet, "met_hideUnderline", false);
//        hideUnderline = attrSet.getAttr("met_hideUnderline").get().getBoolValue();//隐藏底线
        underlineColor = AttrValue.get(attrSet, "met_underlineColor", -1);
//        underlineColor = attrSet.getAttr("met_underlineColor").get().getIntegerValue();//输入框底线颜色
        underlineHeight = AttrValue.get(attrSet, "met_underlineHeight", AttrHelper.vp2px(1, context));
//        underlineHeight = AttrHelper.vp2px(1,context);  // 输入框底线的高度,默认1dp
        underlineHeightFocused = AttrValue.get(attrSet, "met_underlineHeightFocused", AttrHelper.vp2px(2, context));
//        underlineHeightFocused = AttrHelper.vp2px(2,context);//输入框聚焦时底线的高度，默认2dp
        autoValidate = AttrValue.get(attrSet, "met_autoValidate", false);
//        autoValidate = attrSet.getAttr("met_autoValidate").get().getBoolValue();//是否自动校验

        iconLeftBitmaps = generateIconBitmaps(AttrValue.get(attrSet, "met_iconLeft", -1));
//        iconLeftBitmaps = generateIconBitmaps(attrSet.getAttr("met_iconLeft").get().getIntegerValue(),-1);//左侧图标资源
        iconRightBitmaps = generateIconBitmaps(AttrValue.get(attrSet, "met_iconRight", -1));
//        iconRightBitmaps = generateIconBitmaps(attrSet.getAttr("met_iconRight").get().getIntegerValue());//右侧图标资源
        showClearButton = AttrValue.get(attrSet, "met_clearButton", false);//是否使用清除按钮
//        showClearButton = attrSet.getAttr("met_clearButton").get().getBoolValue();//是否使用清除按钮
        System.out.println("zhangliang==>init6");

        clearButtonBitmaps = generateIconBitmaps(ResourceTable.Media_xui_ic_default_clear_btn);
        showPasswordButton = AttrValue.get(attrSet, "met_passWordButton", false);
//        showPasswordButton = attrSet.getAttr("met_passWordButton").get().getBoolValue();// 是否使用显示密码按钮

        boolean isAsteriskStyle = AttrValue.get(attrSet, "met_isAsteriskStyle", false);//密码输入框文字的样式是否是“*”，默认是false
        //密码显示的方式
        if (isAsteriskStyle) {
            setTextInputType(InputAttribute.PATTERN_PASSWORD);
        } else {
            setTextInputType(InputAttribute.PATTERN_TEXT);
        }
        if (showPasswordButton) {
            //密码显示切换
//            handleSwitchPasswordInputVisibility();
        }
        System.out.println("zhangliang==>init7");
//        VectorElement vectorElement = new VectorElement(context,ResourceTable.Graphic_pet_icon_visibility_off_dp);
        showPwIconBitmaps = generateIconBitmaps(ResourceTable.Media_pet_icon_visibility);
        System.out.println("zhangliang==>init71");
        hidePwIconBitmaps = generateIconBitmaps(ResourceTable.Media_pet_icon_visibility_off);
//        showPwIconBitmaps = new VectorElement(context,ResourceTable.Graphic_pet_icon_visibility_off_dp);
//        hidePwIconBitmaps = new VectorElement(getContext(), ResourceTable.Graphic_pet_icon_visibility_dp);
        //met_regexp
        String regexp = AttrValue.get(attrSet, "met_regexp", "");
//        String regexp = attrSet.getAttr("met_regexp").get().getStringValue();
        if (!TextUtils.isEmpty(regexp)) {
            String errorMessage = attrSet.getAttr("met_errorMessage").get().getStringValue();
            if (!TextUtils.isEmpty(errorMessage)) {
                validators.add(new RegexpValidator(errorMessage, regexp));
            } else {
                validators.add(new RegexpValidator("输入不符合要求!", regexp));
            }
        }
        System.out.println("zhangliang==>init8");
        iconPadding = AttrValue.get(attrSet, "met_iconPadding", AttrHelper.vp2px(8, context));
//        iconPadding = AttrHelper.vp2px(8,context);//图标与输入区域的距离（默认8dp）
        floatingLabelAlwaysShown = AttrValue.get(attrSet, "met_floatingLabelAlwaysShown", false);
//        floatingLabelAlwaysShown = attrSet.getAttr("met_floatingLabelAlwaysShown").get().getBoolValue();//悬浮提示一直显示（而不是通过动画显示／消失，默认false）
        helperTextAlwaysShown = AttrValue.get(attrSet, "met_helperTextAlwaysShown", false);
//        helperTextAlwaysShown = attrSet.getAttr("met_helperTextAlwaysShown").get().getBoolValue();//是否一直显示辅助性文字（错误提示），无论是否在焦点。（默认false）
        validateOnFocusLost = AttrValue.get(attrSet, "met_validateOnFocusLost", false);
//        validateOnFocusLost = attrSet.getAttr("met_validateOnFocusLost").get().getBoolValue();//是否失去焦点后自动校验（默认false）
        checkCharactersCountAtBeginning = AttrValue.get(attrSet, "met_validateOnFocusLost", true);
//        checkCharactersCountAtBeginning = attrSet.getAttr("met_checkCharactersCountAtBeginning").get().getBoolValue();//是否在文字显示的时候开始计算文字的数量（默认true）


//        int padding = AttrHelper.vp2px(0, context);
        innerPaddingLeft = AttrHelper.vp2px(1, context);
        innerPaddingTop = AttrHelper.vp2px(2, context);
        innerPaddingRight = AttrHelper.vp2px(3, context);
        innerPaddingBottom = AttrHelper.vp2px(4, context);
        System.out.println("zhangliang==>init9");
//        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
//            setBackground(null);
//        } else {
//            setBackgroundDrawable(null);
//        }
        setBackground(null);

        if (singleLineEllipsis) {
//            TransformationMethod transformationMethod = getTransformationMethod();
//            setSingleLine();
//            setTransformationMethod(transformationMethod);
        }
        System.out.println("zhangliang==>init10");
        initMinBottomLines();
        initPadding();
        initText();
        initFloatingLabel();
        initTextWatcher();
        checkCharactersCount();
        addDrawTask(task);
        setTouchEventListener(this);
        System.out.println("zhangliang==>init11");

    }

    private void setFloatingLabelInternal(int mode) {
        switch (mode) {
            case FLOATING_LABEL_NORMAL:
                floatingLabelEnabled = true;
                highlightFloatingLabel = false;
                break;
            case FLOATING_LABEL_HIGHLIGHT:
                floatingLabelEnabled = true;
                highlightFloatingLabel = true;
                break;
            default:
                setBubbleHeight(0);
                setBubbleWidth(0);
                floatingLabelEnabled = false;
                highlightFloatingLabel = false;
                break;
        }
    }

    private PixelMap[] generateIconBitmaps(int origin) {
        if (origin <= 0) return null;
        InputStream is = null;
        try {
            // 读取资源
            is = getContext().getResourceManager().getResource(origin);
            // 创建ImageOptions
            ImageSource.SourceOptions sourceOptions = new ImageSource.SourceOptions();
            sourceOptions.formatHint = "image/jpg";
            // 创建ImageSource
            ImageSource imageSource = ImageSource.create(is, sourceOptions);

            // 创建解码器DecodingOptions
            ImageSource.DecodingOptions decodingOptions = new ImageSource.DecodingOptions();

            decodingOptions.desiredSize = new Size(AttrHelper.vp2px(25.0f, getContext()), AttrHelper.vp2px(25.0f, getContext()));

            // 创建mapX
            return generateIconBitmaps(imageSource.createPixelmap(decodingOptions));
        } catch (IOException | NotExistException e) {
            e.printStackTrace();
        } finally {
            try {
                if (is != null)
                    is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    private PixelMap[] generateIconBitmaps(PixelMap origin) {
        if (origin == null) {
            return null;
        }
        PixelMap[] iconBitmaps = new PixelMap[4];
        origin = scaleIcon(origin);
        iconBitmaps[0] = PixelMap.create(origin, null);
        Canvas canvas = new Canvas(new Texture(iconBitmaps[0]));
        canvas.drawColor(baseColor & 0x00ffffff | (isLight(baseColor) ? 0xff000000 : 0x8a000000), Canvas.PorterDuffMode.SRC_IN);
        iconBitmaps[1] = PixelMap.create(origin, null);
        canvas = new Canvas(new Texture(iconBitmaps[1]));
        canvas.drawColor(primaryColor, Canvas.PorterDuffMode.SRC_IN);
        iconBitmaps[2] = PixelMap.create(origin, null);
        canvas = new Canvas(new Texture(iconBitmaps[2]));
        canvas.drawColor(baseColor & 0x00ffffff | (isLight(baseColor) ? 0x4c000000 : 0x42000000), Canvas.PorterDuffMode.SRC_IN);
        iconBitmaps[3] = PixelMap.create(origin, null);
        canvas = new Canvas(new Texture(iconBitmaps[3]));
        canvas.drawColor(errorColor, Canvas.PorterDuffMode.SRC);
        return iconBitmaps;
    }

    public boolean isLight(int color) {
        //获取高亮，当高亮大于130,则返回true，否则false
        return HsvColor.toHSV(color).getValue() >= (130 / 255) ? true : false;
    }

    private PixelMap scaleIcon(PixelMap origin) {
        int width = origin.getImageInfo().size.width;
        int height = origin.getImageInfo().size.height;
        int size = Math.max(width, height);
        if (size == iconSize) {
            return origin;
        } else if (size > iconSize) {
            int scaledWidth;
            int scaledHeight;
            if (width > iconSize) {
                scaledWidth = iconSize;
                scaledHeight = (int) (iconSize * ((float) height / width));
            } else {
                scaledHeight = iconSize;
                scaledWidth = (int) (iconSize * ((float) width / height));
            }
//            PixelMap.InitializationOptions options = new PixelMap.InitializationOptions();

            Rect rect = new Rect();
            rect.width = scaledWidth;
            rect.height = scaledHeight;
            return PixelMap.create(origin, rect, null);
        } else {
            return origin;
        }
    }


    /**
     * calculate {@link #minBottomLines}
     */
    private void initMinBottomLines() {
        boolean extendBottom = minCharacters > 0 || maxCharacters > 0 || singleLineEllipsis || tempErrorText != null || helperText != null;
        currentBottomLines = minBottomLines = minBottomTextLines > 0 ? minBottomTextLines : extendBottom ? 1 : 0;
    }

    private void initPadding() {
        extraPaddingTop = floatingLabelEnabled ? floatingLabelTextSize + floatingLabelPadding : floatingLabelPadding;
        textPaint.setTextSize(bottomTextSize);
        Paint.FontMetrics textMetrics = textPaint.getFontMetrics();
        extraPaddingBottom = (int) ((textMetrics.descent - textMetrics.ascent) * currentBottomLines) + (hideUnderline ? bottomSpacing : bottomSpacing * 2);
        extraPaddingLeft = getStartIcon() == null ? 0 : (iconOuterWidth + iconPadding);
        extraPaddingRight = getEndIcon() == null ? 0 : (iconOuterWidth + iconPadding);
        correctPaddings();
    }

    private PixelMap[] getStartIcon() {
        return isRTL() ? iconRightBitmaps : iconLeftBitmaps;
    }

    private PixelMap[] getEndIcon() {
        return isRTL() ? iconLeftBitmaps : iconRightBitmaps;
    }

    private boolean isRTL() {
        return getLayoutDirection() == LayoutDirection.RTL;
    }

    /**
     * Set paddings to the correct values
     */
    private void correctPaddings() {
        int buttonsWidthLeft = 0, buttonsWidthRight = 0;
        int buttonsWidth = iconOuterWidth * getButtonsCount();
        if (isRTL()) {
            buttonsWidthLeft = buttonsWidth;
        } else {
            buttonsWidthRight = buttonsWidth;
        }
        super.setPaddingRelative(innerPaddingLeft + extraPaddingLeft + buttonsWidthLeft, innerPaddingTop + extraPaddingTop, innerPaddingRight + extraPaddingRight + buttonsWidthRight, innerPaddingBottom + extraPaddingBottom);
    }

    private int getButtonsCount() {
        return isShowClearButton() || isShowPasswordButton() ? 1 : 0;
    }

    public boolean isShowClearButton() {
        return showClearButton;
    }

    public boolean isShowPasswordButton() {
        return showPasswordButton;
    }


    private void initText() {
        if (!TextUtils.isEmpty(getText())) {
            CharSequence text = getText();
            setText(null);
            resetHintTextColor();
            setText(text.toString());
//            setSelection(text != null ? text.length() : 0);
          /*  new CursorChangedListener() {
                @Override
                public void onCursorChange(TextField textField, int i, int i1) {
                    i1 = text != null ? text.length() : 0;
                }
            };*/
            floatingLabelFraction = 1;
            floatingLabelShown = true;
        } else {
            resetHintTextColor();
        }
        resetTextColor();
    }

    private void resetHintTextColor() {
        if (textColorHintStateList == null) {
            setHintColor(Color.GRAY);
        } else {
            setHintColor(textColorHintStateList);
        }
    }

    private void resetTextColor() {
        if (textColorStateList == null) {
            textColorStateList = Color.GRAY;
            setTextColor(textColorStateList);
        } else {
            setTextColor(textColorStateList);
        }
    }

    private void initFloatingLabel() {
        // observe the text changing
        addTextObserver(new TextObserver() {
            @Override
            public void onTextUpdated(String s, int i, int i1, int i2) {
                if (floatingLabelEnabled) {
                    if (s.length() == 0) {
                        if (floatingLabelShown) {
                            floatingLabelShown = false;
                            getLabelAnimator().release();
                        }
                    } else if (!floatingLabelShown) {
                        floatingLabelShown = true;
                        getLabelAnimator().start();
                    }
                }
            }
        });
        // observe the focus state to animate the floating label's text color appropriately
        innerFocusChangeListener = new FocusChangedListener() {

            @Override
            public void onFocusChange(Component component, boolean b) {
                if (floatingLabelEnabled && highlightFloatingLabel) {
                    if (b) {
                        getLabelFocusAnimator().start();
                    } else {
                        getLabelFocusAnimator().release();
                    }
                }
                if (validateOnFocusLost && !b) {
                    validate();
                }
                if (outerFocusChangeListener != null) {
                    outerFocusChangeListener.onFocusChange(component, b);
                }
            }
        };
        setFocusChangedListener(innerFocusChangeListener);
    }

    private AnimatorValue getLabelAnimator() {
        if (labelAnimator == null) {
            labelAnimator = new AnimatorValue();
            labelAnimator.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {
                @Override
                public void onUpdate(AnimatorValue animatorValue, float v) {
                    System.out.println("zhangliang==>" + v);
                }
            });
        }
        labelAnimator.setDuration(floatingLabelAnimating ? 300 : 0);
        return labelAnimator;
    }

    private AnimatorValue getLabelFocusAnimator() {
        if (labelFocusAnimator == null) {
            labelFocusAnimator = new AnimatorValue();
            labelFocusAnimator.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {
                @Override
                public void onUpdate(AnimatorValue animatorValue, float v) {
                    System.out.println("zhangliang==>" + v);
                }
            });
        }
        return labelFocusAnimator;
    }

    /**
     * 检查所有验证程序，如果没有，则设置错误文本
     * <p/>
     * 注意：这将在第一个报告无效的验证器处停止。
     *
     * @return True如果所有验证都通过，否则返回false
     */
    public boolean validate() {
        if (validators == null || validators.isEmpty()) {
            return true;
        }

        CharSequence text = getText();
        boolean isEmpty = TextUtils.isEmpty(text);

        boolean isValid = true;
        for (METValidator validator : validators) {
            //noinspection ConstantConditions
            isValid = isValid && validator.isValid(text, isEmpty);
            if (!isValid) {
//                setError(validator.getErrorMessage());
                System.out.println("zhangliang==>setError" + validator.getErrorMessage());
                break;
            }
        }
        if (isValid) {
            System.out.println("zhangliang==>setError null");
//            setError(null);
        }
        invalidate();
//        postInvalidate();
        return isValid;
    }

    private void initTextWatcher() {
        addTextObserver(new TextObserver() {

            @Override
            public void onTextUpdated(String s, int i, int i1, int i2) {
                checkCharactersCount();
                if (autoValidate) {
                    validate();
                } else {
//                    setError(null);
                    System.out.println("zhangliang==>setError null");
                }
                invalidate();
            }
        });
    }

    private void checkCharactersCount() {
        if ((!firstShown && !checkCharactersCountAtBeginning) || !hasCharactersCounter()) {
            charactersCountValid = true;
        } else {
            CharSequence text = getText();
            int count = text == null ? 0 : checkLength(text);
            charactersCountValid = (count >= minCharacters && (maxCharacters <= 0 || count <= maxCharacters));
        }
    }

    private boolean hasCharactersCounter() {
        return minCharacters > 0 || maxCharacters > 0;
    }

    private int checkLength(CharSequence text) {
        if (lengthChecker == null) {
            return text.length();
        }
        return lengthChecker.getLength(text);
    }


    private int getCharactersCounterWidth() {
        return hasCharactersCounter() ? (int) textPaint.measureText(getCharactersCounterText()) : 0;
    }

    private int getBottomEllipsisWidth() {
        return singleLineEllipsis ? (bottomEllipsisSize * 5 + AttrHelper.vp2px(4, getContext())) : 0;
    }

    private String getCharactersCounterText() {
        String text;
        if (minCharacters <= 0) {
            text = isRTL() ? maxCharacters + " / " + checkLength(getText()) : checkLength(getText()) + " / " + maxCharacters;
        } else if (maxCharacters <= 0) {
            text = isRTL() ? "+" + minCharacters + " / " + checkLength(getText()) : checkLength(getText()) + " / " + minCharacters + "+";
        } else {
            text = isRTL() ? maxCharacters + "-" + minCharacters + " / " + checkLength(getText()) : checkLength(getText()) + " / " + minCharacters + "-" + maxCharacters;
        }
        return text;
    }

    private AnimatorValue getBottomLinesAnimator(float destBottomLines) {
        if (bottomLinesAnimator == null) {
//            bottomLinesAnimator = AnimatorValue.ofFloat(this, "currentBottomLines", destBottomLines);
        } else {
            bottomLinesAnimator.cancel();
//            bottomLinesAnimator.AnimatorValue(destBottomLines);
        }
//        return bottomLinesAnimator;
        return bottomLinesAnimator;
    }

    @Override
    public final void setPadding(int left, int top, int right, int bottom) {
        super.setPadding(left, top, right, bottom);
    }

    /**
     * Use this method instead of {@link #setPadding(int, int, int, int)} to automatically set the paddingTop and the paddingBottom correctly.
     *
     * @param left
     * @param top
     * @param right
     * @param bottom
     * @return MaterialTextField
     */
    public MaterialTextField setPaddings(int left, int top, int right, int bottom) {
        innerPaddingTop = top;
        innerPaddingBottom = bottom;
        innerPaddingLeft = left;
        innerPaddingRight = right;
        correctPaddings();
        return this;
    }

    @Override
    public boolean isBoundToWindow() {
        super.isBoundToWindow();
        if (!firstShown) {
            firstShown = true;
        }
        return firstShown;
    }


    @Override
    public boolean onArrange(int i, int i1, int i2, int i3) {
        // i=左，i1=顶部，i2=宽度，i3=高度
        adjustBottomLines();
        return false;
    }

    /**
     * adjustBottomLines
     *
     * @return True, if adjustments were made that require the view to be invalidated.
     */
    private boolean adjustBottomLines() {
        // Bail out if we have a zero width; lines will be adjusted during next layout.
        if (getWidth() == 0) {
            return false;
        }
        int destBottomLines;
        textPaint.setTextSize(bottomTextSize);
        if (tempErrorText != null || helperText != null) {
//            TextAlignment alignment = (getTextAlignment() & TextAlignment.END) == TextAlignment.END|| isRTL() ?
//                    TextAlignment.ALIGN_OPPOSITE : (getTextAlignment() & TextAlignment.START) == TextAlignment.START ?
//                    TextAlignment.ALIGN_NORMAL : TextAlignment.CENTER;
            ohos.agp.utils.Rect rect = new ohos.agp.utils.Rect();
            rect.left = AttrHelper.vp2px(20, getContext());
            rect.right = AttrHelper.vp2px(20, getContext());
            rect.bottom = AttrHelper.vp2px(20, getContext());
            rect.top = AttrHelper.vp2px(20, getContext());
            textLayout = new SimpleTextLayout(tempErrorText != null ? tempErrorText : helperText, textPaint, rect, getWidth() - getBottomTextLeftOffset() - getBottomTextRightOffset() - getPaddingLeft() - getPaddingRight(), isRTL());
            destBottomLines = Math.max(textLayout.getLineCount(), minBottomTextLines);
        } else {
            destBottomLines = minBottomLines;
        }
        if (bottomLines != destBottomLines) {
            getBottomLinesAnimator(destBottomLines).start();
        }
        bottomLines = destBottomLines;
        return true;
    }

    private int getBottomTextLeftOffset() {
        return isRTL() ? getCharactersCounterWidth() : getBottomEllipsisWidth();
    }

    private int getBottomTextRightOffset() {
        return isRTL() ? getBottomEllipsisWidth() : getCharactersCounterWidth();
    }


    public void setError(CharSequence errorText) {
        tempErrorText = errorText == null ? null : errorText.toString();
        if (adjustBottomLines()) {
            invalidate();
        }
    }

    public CharSequence getError() {
        return tempErrorText;
    }

    /**
     * if the main text matches the regex
     *
     * @param regex use the new validator interface to add your own custom validator
     * @return boolean
     */
    @Deprecated
    public boolean isValid(String regex) {
        if (regex == null) {
            return false;
        }
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(getText());
        return matcher.matches();
    }

    /**
     * check if the main text matches the regex, and set the error text if not.
     *
     * @param regex use the new validator interface to add your own custom validator
     * @param errorText
     * @return true if it matches the regex, false if not.
     */
    @Deprecated
    public boolean validate(String regex, CharSequence errorText) {
        boolean isValid = isValid(regex);
        if (!isValid) {
            setError(errorText);
        }
        invalidate();
        return isValid;
    }

    @Override
    public void setEnabled(boolean enabled) {
        if (enabled) {
            super.setFocusable(FOCUS_ENABLE);
        } else {
            super.setFocusable(FOCUS_DISABLE);
        }
        super.setBubbleSize(0, 0);
        super.setEnabled(enabled);
    }

    @Override
    public void setFocusChangedListener(FocusChangedListener listener) {
        if (innerFocusChangeListener == null) {
            super.setFocusChangedListener(listener);
        } else {
            outerFocusChangeListener = listener;
        }
    }

    DrawTask task = new DrawTask() {
        @Override
        public void onDraw(Component component, Canvas canvas) {
            System.out.println("zhangliang==>111111111111111");
            int startX = getScrollValue(AXIS_X) + (getStartIcon() == null ? 0 : iconOuterWidth + iconPadding);
            int endX = getScrollValue(AXIS_X) + (getEndIcon() == null ? getWidth() : getWidth() - iconOuterWidth - iconPadding);
            int lineStartY = getScrollValue(AXIS_Y) + getHeight() - getPaddingBottom();

            // draw the icon(s)
            drawIcons(canvas, startX, endX, lineStartY);

            // draw the action button
            drawActionButton(canvas, startX, endX, lineStartY);

            // draw the underline
            lineStartY = drawUnderline(canvas, startX, endX, lineStartY);

            textPaint.setTextSize(bottomTextSize);
            Paint.FontMetrics textMetrics = textPaint.getFontMetrics();
            float relativeHeight = -textMetrics.ascent - textMetrics.descent;
            float bottomTextPadding = bottomTextSize + textMetrics.ascent + textMetrics.descent;

            // draw the characters counter
            if ((hasFocus() && hasCharactersCounter()) || !isCharactersCountValid()) {
                textPaint.setColor(new Color(isCharactersCountValid() ? (baseColor & 0x00ffffff | 0x44000000) : errorColor));
                String charactersCounterText = getCharactersCounterText();
                canvas.drawText(textPaint, charactersCounterText, isRTL() ? startX : endX + getPaddingEnd() - textPaint.measureText(charactersCounterText), lineStartY + bottomSpacing + relativeHeight);
//                canvas.drawText(charactersCounterText, isRTL() ? startX : endX + getPaddingEnd() - textPaint.measureText(charactersCounterText), lineStartY + bottomSpacing + relativeHeight, textPaint);
            }

            // draw the bottom text
            drawBottomText(canvas, startX, endX, lineStartY, bottomTextPadding);

            // draw the floating label
            drawFloatingLabel(canvas, startX, endX);

            // draw the bottom ellipsis
            drawBottomEllipsis(canvas, startX, endX, lineStartY);

            // draw the original things
//            super.onDraw(canvas);
        }
    };

    /**
     * 画图标
     *
     * @param canvas
     * @param startX
     * @param endX
     * @param lineStartY
     */
    private void drawIcons(Canvas canvas, int startX, int endX, int lineStartY) {
        paint.setAlpha(255);
        if (getStartIcon() != null) {
            PixelMap icon = getStartIcon()[!isInternalValid() ? 3 : !isEnabled() ? 2 : hasFocus() ? 1 : 0];
            int iconLeft = startX - iconPadding - iconOuterWidth + (iconOuterWidth - icon.getImageInfo().size.width) / 2;
            int iconTop = lineStartY + bottomSpacing - iconOuterHeight + (iconOuterHeight - icon.getImageInfo().size.height) / 2;
//            canvas.drawBitmap(icon, iconLeft, iconTop, paint);
            canvas.drawPixelMapHolder(new PixelMapHolder(icon), iconLeft, iconTop, paint);
        }
        if (getEndIcon() != null) {
            PixelMap icon = getEndIcon()[!isInternalValid() ? 3 : !isEnabled() ? 2 : hasFocus() ? 1 : 0];
            int iconRight = endX + iconPadding + (iconOuterWidth - icon.getImageInfo().size.width) / 2;
            int iconTop = lineStartY + bottomSpacing - iconOuterHeight + (iconOuterHeight - icon.getImageInfo().size.height) / 2;
            canvas.drawPixelMapHolder(new PixelMapHolder(icon), iconRight, iconTop, paint);
        }
    }

    /**
     * only used to draw the bottom line
     *
     * @return boolean
     */
    private boolean isInternalValid() {
        return tempErrorText == null && isCharactersCountValid();
    }

    public boolean isCharactersCountValid() {
        return charactersCountValid;
    }

    /**
     * 画清除按钮
     *
     * @param canvas
     * @param startX
     * @param endX
     * @param lineStartY
     */
    private void drawActionButton(Canvas canvas, int startX, int endX, int lineStartY) {
        if (hasFocus() && isEnabled() && !TextUtils.isEmpty(getText()) && (showClearButton || showPasswordButton)) {
            paint.setAlpha(255);
            int buttonLeft = isRTL() ? startX : endX - iconOuterWidth;
            PixelMap actionButtonBitmap;
            if (showClearButton) {
                actionButtonBitmap = clearButtonBitmaps[0];
            } else {
                actionButtonBitmap = passwordVisible ? showPwIconBitmaps[0] : hidePwIconBitmaps[0];
            }
            int iconTop = lineStartY + bottomSpacing - iconOuterHeight + (iconOuterHeight - actionButtonBitmap.getImageInfo().size.height) / 2;
            canvas.drawPixelMapHolder(new PixelMapHolder(actionButtonBitmap), buttonLeft, iconTop, paint);
        }
    }

    /**
     * 画下划线
     *
     * @param canvas
     * @param startX
     * @param endX
     * @param lineStartY
     * @return int
     */
    private int drawUnderline(Canvas canvas, int startX, int endX, int lineStartY) {
        System.out.println("zhangliang==>11111" + hasFocus());
        if (!hideUnderline) {
            lineStartY += bottomSpacing;
            if (!isInternalValid()) { // not valid
                paint.setColor(new Color(errorColor));
                canvas.drawRect(startX, lineStartY, endX, lineStartY + underlineHeightFocused, paint);
            } else if (!isEnabled()) { // disabled
                paint.setColor(new Color(underlineColor != -1 ? underlineColor : baseColor & 0x00ffffff | 0x44000000));
                float interval = AttrHelper.vp2px(1, getContext());
                for (float xOffset = 0; xOffset < getWidth(); xOffset += interval * 3) {
                    canvas.drawRect(startX + xOffset, lineStartY, startX + xOffset + interval, lineStartY + underlineHeight, paint);
                }
            } else if (hasFocus()) { // focused
                paint.setColor(new Color(primaryColor));
                canvas.drawRect(startX, lineStartY, endX, lineStartY + underlineHeightFocused, paint);
            } else { // normal
                paint.setColor(new Color(underlineColor != -1 ? underlineColor : baseColor & 0x00ffffff | 0x1E000000));
                canvas.drawRect(startX, lineStartY, endX, lineStartY + underlineHeight, paint);
            }
        }
        return lineStartY;
    }

    /**
     * 画底部文字
     *
     * @param canvas
     * @param startX
     * @param endX
     * @param lineStartY
     * @param bottomTextPadding
     */
    private void drawBottomText(Canvas canvas, int startX, int endX, int lineStartY, float bottomTextPadding) {
        if (textLayout != null) {
            if (tempErrorText != null || ((helperTextAlwaysShown || hasFocus()) && !TextUtils.isEmpty(helperText))) { // error text or helper text
                textPaint.setColor(new Color(tempErrorText != null ? errorColor : helperTextColor != -1 ? helperTextColor : (baseColor & 0x00ffffff | 0x44000000)));
                canvas.save();
                if (isRTL()) {
                    canvas.translate(endX - textLayout.getWidth(), lineStartY + bottomSpacing - bottomTextPadding);
                } else {
                    canvas.translate(startX + getBottomTextLeftOffset(), lineStartY + bottomSpacing - bottomTextPadding);
                }
                textLayout.drawText(canvas);
                canvas.restore();
            }
        }
    }

    /**
     * get inner left padding, not the real paddingLeft
     *
     * @return int
     */
    public int getInnerPaddingLeft() {
        return innerPaddingLeft;
    }

    /**
     * get inner right padding, not the real paddingRight
     *
     * @return int
     */
    public int getInnerPaddingRight() {
        return innerPaddingRight;
    }


    private void drawFloatingLabel(Canvas canvas, int startX, int endX) {
        if (floatingLabelEnabled && !TextUtils.isEmpty(floatingLabelText)) {
            textPaint.setTextSize(floatingLabelTextSize);
            // calculate the text color
            ColorUtils.evaluate(focusFraction * (isEnabled() ? 1 : 0), floatingLabelTextColor != -1 ? floatingLabelTextColor : (baseColor & 0x00ffffff | 0x44000000), primaryColor);
            textPaint.setColor(new Color((Integer) ColorUtils.evaluate(focusFraction * (isEnabled() ? 1 : 0), floatingLabelTextColor != -1 ? floatingLabelTextColor : (baseColor & 0x00ffffff | 0x44000000), primaryColor)));

            // calculate the horizontal position
            float floatingLabelWidth = textPaint.measureText(floatingLabelText.toString());
            int floatingLabelStartX;
            if ((getTextAlignment() & TextAlignment.RIGHT) == TextAlignment.RIGHT || isRTL()) {
                floatingLabelStartX = (int) (endX - floatingLabelWidth);
            } else if ((getTextAlignment() & TextAlignment.LEFT) == TextAlignment.LEFT) {
                floatingLabelStartX = startX;
            } else {
                floatingLabelStartX = startX + (int) (getInnerPaddingLeft() + (getWidth() - getInnerPaddingLeft() - getInnerPaddingRight() - floatingLabelWidth) / 2);
            }

            // calculate the vertical position
            int distance = floatingLabelPadding;
            int floatingLabelStartY = (int) (innerPaddingTop + floatingLabelTextSize + floatingLabelPadding - distance * (floatingLabelAlwaysShown ? 1 : floatingLabelFraction) + getScrollValue(AXIS_Y));

            // calculate the alpha
            int alpha = ((int) ((floatingLabelAlwaysShown ? 1 : floatingLabelFraction) * 0xff * (0.74f * focusFraction * (isEnabled() ? 1 : 0) + 0.26f) * (floatingLabelTextColor != -1 ? 1 : Color.alpha(floatingLabelTextColor) / 255F)));
            textPaint.setAlpha(alpha);

            // draw the floating label
            canvas.drawText(textPaint, floatingLabelText.toString(), floatingLabelStartX, floatingLabelStartY);
        }
    }

    private void drawBottomEllipsis(Canvas canvas, int startX, int endX, int lineStartY) {
        if (hasFocus() && singleLineEllipsis && getScrollValue(AXIS_X) != 0) {
            paint.setColor(new Color(isInternalValid() ? primaryColor : errorColor));
            float startY = lineStartY + bottomSpacing;
            int ellipsisStartX;
            if (isRTL()) {
                ellipsisStartX = endX;
            } else {
                ellipsisStartX = startX;
            }
            int signum = isRTL() ? -1 : 1;
            canvas.drawCircle(ellipsisStartX + signum * bottomEllipsisSize / 2F, startY + bottomEllipsisSize / 2F, bottomEllipsisSize / 2F, paint);
            canvas.drawCircle(ellipsisStartX + signum * bottomEllipsisSize * 5 / 2F, startY + bottomEllipsisSize / 2F, bottomEllipsisSize / 2F, paint);
            canvas.drawCircle(ellipsisStartX + signum * bottomEllipsisSize * 9 / 2F, startY + bottomEllipsisSize / 2F, bottomEllipsisSize / 2F, paint);
        }
    }


    @Override
    public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
        if (singleLineEllipsis && getScrollValue(AXIS_Y) > 0 && touchEvent.getAction() == TouchEvent.OTHER_POINT_DOWN && touchEvent.getPointerScreenPosition(0).getX() < AttrHelper.vp2px(4 * 5, getContext()) && touchEvent.getPointerScreenPosition(0).getY() > getHeight() - extraPaddingBottom - innerPaddingBottom && touchEvent.getPointerScreenPosition(0).getY() < getHeight() - innerPaddingBottom) {
//            setSelection(0);
            return false;
        }
        if (hasFocus() && (showClearButton || showPasswordButton) && isEnabled()) {
            switch (touchEvent.getAction()) {
                case TouchEvent.OTHER_POINT_DOWN:
                    if (insideActionButton(touchEvent)) {
                        actionButtonTouched = true;
                        actionButtonClicking = true;
                        return true;
                    }
                case TouchEvent.POINT_MOVE:
                    if (actionButtonClicking && !insideActionButton(touchEvent)) {
                        actionButtonClicking = false;
                    }
                    if (actionButtonTouched) {
                        return true;
                    }
                    break;
                case TouchEvent.OTHER_POINT_UP:
                    if (actionButtonClicking) {
                        if (showClearButton) {
                            if (!TextUtils.isEmpty(getText())) {
                                setText(null);
                            }
                        } else {
                            togglePasswordIconVisibility();
                        }
                        actionButtonClicking = false;
                    }
                    if (actionButtonTouched) {
                        actionButtonTouched = false;
                        return true;
                    }
                    actionButtonTouched = false;
                    break;
                case TouchEvent.CANCEL:
                    actionButtonTouched = false;
                    actionButtonClicking = false;
                    break;
                default:
                    break;
            }
        }
        return true;
    }

    private boolean insideActionButton(TouchEvent event) {
        float x = event.getPointerScreenPosition(0).getX();
        float y = event.getPointerScreenPosition(0).getY();
        int startX = getStartIcon() == null ? 0 : iconOuterWidth + iconPadding;
        int endX = getEndIcon() == null ? getWidth() : getWidth() - iconOuterWidth - iconPadding;
        int buttonLeft = isRTL() ? startX : endX - iconOuterWidth;
        int buttonTop = getScrollValue(AXIS_Y) + getHeight() - getPaddingBottom() + bottomSpacing - iconOuterHeight;
        return (x >= buttonLeft && x < buttonLeft + iconOuterWidth && y >= buttonTop && y < buttonTop + iconOuterHeight);
    }

    /**
     * 密码显示切换
     */
    private void togglePasswordIconVisibility() {
        passwordVisible = !passwordVisible;
        handleSwitchPasswordInputVisibility();
    }

    /**
     * 密码显示切换
     */
    private void handleSwitchPasswordInputVisibility() {
//        int selectionStart = getSelectionStart();
//        int selectionEnd = getSelectionEnd();
//        if (passwordVisible) {
//            setTransformationMethod(null);
//        } else {
//            setTransformationMethod(mTransformationMethod);
//
//        }
//        setSelection(selectionStart, selectionEnd);
    }

    public void setColor(int color) {
        setTextColor(new Color(color));
    }
}
